<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    
<button class="btn">按钮</button>

<script>
// this是一个指针型变量
// 学习this有两个目标：1 2
// 1.能够判断this指向
// 2.会修改this的指向

// 判断this指向：
// 1.在全局中，this指向window对象
console.log( this );// window

// 2.在函数中，this指向函数的调用对象
var obj = {
    name: '张三',
    say: function (){
        console.log( this.name );
    }
}
obj.say();// this -> obj

// 3.在事件处理函数中，this指向添加事件的DOM元素
btn.onclick = function (){
    console.log( this );// btn
}

// 4.在构造函数或原型对象的方法中，this通常指向实例对象
function Human(n){
    this.name = n;
}
Human.prototype.say = function (){
    console.log( this.name );
}
Human('小王');// this -> window
Human.prototype.say();// this -> Human.prototype
var person1 = new Human('老王');// this -> 创建的实例对象
person1.say();// this -> person1实例对象

// 5.在函数中，如果找不到函数的调用对象，则指向window对象
function show(){
    console.log( this );
}
show();// this -> widnow

setTimeout(function (){
    console.log( this );// this -> window
},1000)


/* // 修改this的指向：
// bind(obj,参数1,参数2...)修改函数内部的this指向obj，并返回修改this指向之后的新函数
// obj 要修改this指向的那个对象
// 参数1,参数2... 传递给当前要修改this指向的函数的实参
var a = 1;
var obj1 = {
    a: 2,
    fn: function (b,c){
        console.log( this.a + b + c );
    }
}
var obj2 = {
    a: 6
}

obj1.fn(3,4);// 9 this -> obj1

var sum = obj1.fn.bind(obj2,3,4);
// 上面的代码意味着：1.返回的函数sum绑定了内部this指向obj2；2.sum函数有两个实参3和4
sum();// 13 this -> obj2
console.log( obj1.fn === sum );// false  返回的是一个新函数

setTimeout(function (){
    console.log( this.a );// 1 this -> window
},1000)
setTimeout(function (){
    console.log( this.a );// 2 this -> obj1
}.bind(obj1),1000);// 修改函数内部this指向obj1

var btn = document.querySelector('.btn');
// btn.onclick = function (){
//     console.log( this );// btn
// }
btn.onclick = function (){
    console.log( this );// obj2
}.bind(obj2);// 修改函数内部this指向obj2 */


/* // call(obj,参数1,参数2...)修改函数内部的this指向obj，并执行当前函数,返回值取决于当前函数的返回值
// apply(obj,[参数1,参数2...])修改函数内部的this指向obj，并执行当前函数,返回值取决于当前函数的返回值
// obj 要修改this指向的那个对象
// 参数1,参数2... 传递给当前要修改this指向的函数的实参
var a = 1;
var obj1 = {
    a: 2,
    fn: function (b,c){
        console.log( this.a + b + c );
    }
}
var obj2 = {
    a: 6
}
obj1.fn(3,4);// 9 this -> obj1

obj1.fn.call(this,3,4);// 8 this -> window
obj1.fn.call(obj2,3,4);// 13 this -> obj2

obj1.fn.apply(this,[3,4]);// 8 this -> window
obj1.fn.apply(obj2,[3,4]);// 13 this -> obj2

obj1.fn.bind(this,3,4)();// 8 this -> window
obj1.fn.bind(obj2,3,4)();// 13 this -> obj2

// call和apply的区别：传参的方式不同，call的参数是逗号隔开的参数列表，apply的参数是一个数组

// bind 和 call/apply 的区别：bind不会执行当前函数而是返回一个新的函数,call/apply会执行当前函数

// bind/call/apply共同点: 都可以修改函数内部的this指向 */


var obj3 = {n:1};
var obj4 = {n:2};
var obj5 = {n:3};
function test(){
    console.log( this.n );
}
// test();// undefined this -> window
// test.bind(obj3)();// 1 this -> obj3
// test.call(obj4);// 2 this -> obj4
// test.apply(obj5);// 3 this -> obj5
var newFun = test.bind(obj3).bind(obj4);
newFun();// 1
newFun.call(obj5);// 1
newFun.apply(obj5);// 1

// 注意:使用bind绑定了this指向之后的函数, 不能再修改this指向

</script>
</body>
</html>